home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Think Class Libraries / PixelWorld classes 1.2 / CPixelWorld.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-30  |  24.8 KB  |  955 lines  |  [TEXT/KAHL]

  1. /******************************************************************************
  2.  CPixelWorld.c
  3.  
  4.                             The PixelWorld Class
  5.     
  6.     The CPixelWorld class is a subclass of CBitMap designed to maintain a 
  7.     color offscreen drawing environment using the standard conventions of 
  8.     Color QuickDraw.  An offscreen color graphics device (GDevice) and an 
  9.     offscreen color graphics port (CGrafPort) are used to maintain this 
  10.     offscreen world.  This implementation supports 1,2,4 and 8 bit pixel 
  11.     depths.  Pixel depths of 16 and 32 bits are currently not supported.  
  12.     
  13.     This implementation does not depend upon any 32-Bit QuickDraw features.  
  14.     Future versions of the CPixelWorld class will provide support for pixel 
  15.     depths of 16 and 32 bits, and for GWorlds under 32-Bit QuickDraw.  
  16.     
  17.     SUPERCLASS = CBitMap
  18.     
  19.     This implementation is based in part on material copyrighted by 
  20.     Symantec Corporation and Apple Computer, Inc.  
  21.     
  22.     Copyright © 1992 Vincent R. Vann, Jr.  All rights reserved.  
  23.  
  24.     Version 1.1 Changes:
  25.     [
  26.         - CopyFrom and CopyTo methods were modified so that the foreground 
  27.           and background colors are set to black and white before calling 
  28.           CopyBits.  This ensures that the PixelWorld image is copied with 
  29.           the proper colors.  The foreground and background colors of the 
  30.           current CGrafPort are preserved by these methods. 
  31.     ]
  32.  
  33.     Version 1.2 Changes:
  34.     [
  35.         - added new instance variables saveFgColor and saveBgColor.
  36.         - implemented new methods SaveColors, RestoreColors, 
  37.           CopyFromColors, and CopyToColors.  
  38.         - changed CopyFrom and CopyTo methods to use these color routines.
  39.         - see comments for CopyFromColors and CopyToColors for information 
  40.           about how to colorize your image.  
  41.     ]
  42.  
  43.  ******************************************************************************/
  44.  
  45. #include "CPixelWorld.h"
  46. #include "CDesktop.h"
  47. #include "Exceptions.h"
  48. #include "Global.h"
  49. #include "LongQD.h"
  50. #include "TCLUtilities.h"
  51.  
  52.  
  53. /**** C O N S T R U C T I O N / D E S T R U C T I O N   M E T H O D S ****/
  54.  
  55.  
  56. /******************************************************************************
  57.  IPixelWorld
  58.  
  59.         Initialize a PixelWorld object
  60.  ******************************************************************************/
  61.  
  62. void    CPixelWorld::IPixelWorld(
  63.     short        aPixelDepth,        /* Pixel depth of world in bits        */
  64.     Rect        *aBoundsRect,        /* Bounds rectangle of world        */
  65.     CTabHandle    aColorTable,        /* ColorTable for world    image        */
  66.     Handle        aPixelImage,        /* Handle to pixel image for world    */
  67.     short        aRowBytes)            /* Row bytes of pixel image            */
  68. {
  69.         /* Initialize instance variables of CBitMap superclass */
  70.     
  71.     macPort = NULL;
  72.     savePort = NULL;
  73.     macBitMap = NULL;
  74.     xferMode = srcCopy;
  75.     
  76.         /* Initialize instance variables of CPixelWorld class */
  77.     
  78.     worldIsOK = FALSE;                    /* TRUE if initialized successfully    */
  79.     worldHasColor = gSystem.hasColorQD;    /* TRUE if have Color QuickDraw        */
  80.     worldHas32BitQD = FALSE;            /* TRUE if have 32-Bit QuickDraw    */
  81.     worldOwnsPixels = FALSE;            /* TRUE if world owns pixel image    */
  82.     worldPixelsLocked = FALSE;            /* TRUE if pixel image is locked    */
  83.     
  84.     worldDepth = 0;
  85.     
  86.     worldBounds.left = 0;
  87.     worldBounds.top = 0;
  88.     worldBounds.right = 0;
  89.     worldBounds.bottom = 0;
  90.     
  91.     worldColors = NULL;
  92.     worldDevice = NULL;
  93.     worldPort = NULL;
  94.     worldPixels = NULL;
  95.     
  96.     saveDevice = NULL;
  97.     
  98.     if (!worldHasColor)
  99.         IPixelWorldBW( aPixelDepth, aBoundsRect, aPixelImage, aRowBytes);
  100.     else
  101.         IPixelWorldColor( aPixelDepth, aBoundsRect, aColorTable, aPixelImage, aRowBytes);
  102. }
  103.  
  104.  
  105. /******************************************************************************
  106.  IPixelWorldBW
  107.  
  108.         Initialize a black and white pixel world
  109.  ******************************************************************************/
  110.  
  111. void    CPixelWorld::IPixelWorldBW(
  112.     short        aPixelDepth,        /* Pixel depth of world in bits        */
  113.     Rect        *aBoundsRect,        /* Bounds rectangle of world        */
  114.     Handle        aPixelImage,        /* Handle to pixel image for world    */
  115.     short        aRowBytes)            /* Row bytes of pixel image            */
  116. {
  117.     GrafPtr        theSavedPort;
  118.     Boolean        theSavedAlloc;
  119.     short        rowBytes;
  120.     long        bytes, width, height;
  121.     
  122.     /***
  123.      *** Check for a valid pixel depth
  124.      ***/
  125.     
  126.     if (aPixelDepth != 1) return;
  127.     
  128.     /***
  129.      *** Create the offscreen bitmap
  130.      ***/
  131.     
  132.     width = aBoundsRect->right - aBoundsRect->left;
  133.     height = aBoundsRect->bottom - aBoundsRect->top;
  134.     
  135.     if (aPixelImage != NULL && aRowBytes != 0)
  136.         rowBytes = aRowBytes;
  137.     else
  138.         rowBytes = ((width * aPixelDepth + 31) / 32 ) * 4;
  139.     
  140.     bytes = height * rowBytes;
  141.     
  142.     theSavedAlloc = SetAllocation( kAllocCanFail);
  143.     macBitMap = (BitMap *) NewPtrClear(sizeof(BitMap) + bytes);
  144.     SetAllocation( theSavedAlloc);
  145.     
  146.     FailNIL( macBitMap);
  147.     
  148.     macBitMap->baseAddr = (Ptr) (macBitMap + 1);
  149.     macBitMap->rowBytes = rowBytes;
  150.     macBitMap->bounds = *aBoundsRect;
  151.     
  152.     /***
  153.      *** Copy the existing pixel image into the offscreen bitmap
  154.      ***/
  155.     
  156.     if (aPixelImage != NULL && aRowBytes != 0)
  157.     {
  158.         long    n;
  159.         
  160.         n = GetHandleSize(aPixelImage);
  161.         if (n > 0 && MemError() == noErr)
  162.         {
  163.             if (n > bytes) n = bytes;
  164.             
  165.             HLock( aPixelImage);
  166.             BlockMove( (Ptr) *aPixelImage, macBitMap->baseAddr, n);
  167.             HUnlock( aPixelImage);
  168.         }
  169.     }
  170.     
  171.     /***
  172.      *** Create the offscreen graphics port 
  173.      ***/
  174.     
  175.     theSavedAlloc = SetAllocation( kAllocCanFail);
  176.     macPort = (GrafPtr) NewPtrClear( sizeof(GrafPort));
  177.     SetAllocation( theSavedAlloc);
  178.     
  179.     FailNIL( macPort);
  180.     
  181.     GetPort( &theSavedPort);
  182.     
  183.         OpenPort( macPort);
  184.         SetPort( macPort);
  185.         
  186.         SetPortBits( macBitMap);
  187.         macPort->portRect = *aBoundsRect;
  188.         RectRgn( macPort->visRgn, aBoundsRect);
  189.         RectRgn( macPort->clipRgn, aBoundsRect);
  190.         
  191.     SetPort( theSavedPort);
  192.     
  193.     CView::ForceNextPrepare();
  194.     
  195.     worldIsOK = TRUE;
  196. }
  197.  
  198.  
  199. /******************************************************************************
  200.  IPixelWorldColor
  201.  
  202.         Initialize a color pixel world
  203.  ******************************************************************************/
  204.  
  205. void    CPixelWorld::IPixelWorldColor(
  206.     short        aPixelDepth,        /* Pixel depth of world in bits        */
  207.     Rect        *aBoundsRect,        /* Bounds rectangle of world        */
  208.     CTabHandle    aColorTable,        /* ColorTable for world    image        */
  209.     Handle        aPixelImage,        /* Handle to pixel image for world    */
  210.     short        aRowBytes)            /* Row bytes of pixel image            */
  211. {
  212.     GDHandle    theSavedDevice;
  213.     GrafPtr        theSavedPort;
  214.     Boolean        theSavedAlloc;
  215.     
  216.     /***
  217.      *** Check for a valid pixel depth
  218.      ***/
  219.     
  220.     if (aPixelDepth != 1 && aPixelDepth != 2 && aPixelDepth != 4 && aPixelDepth != 8)
  221.         return;
  222.     
  223.     /***
  224.      *** Set worldDepth and worldBounds instance variables
  225.      ***/
  226.     
  227.     worldDepth = aPixelDepth;
  228.     
  229.     worldBounds.left = aBoundsRect->left;
  230.     worldBounds.top = aBoundsRect->top;
  231.     worldBounds.right = aBoundsRect->right;
  232.     worldBounds.bottom = aBoundsRect->bottom;
  233.     
  234.     /***
  235.      *** Create the world color table
  236.      ***/
  237.     
  238.     if (aColorTable != NULL)        /* Copy the color table */
  239.     {
  240.         OSErr    error;
  241.         
  242.         theSavedAlloc = SetAllocation( kAllocCanFail);
  243.         error = HandToHand( &aColorTable);
  244.         SetAllocation( theSavedAlloc);
  245.         
  246.         FailOSErr(error);
  247.         
  248.         worldColors = aColorTable;
  249.     }
  250.     else                            /* Use standard color table for the pixel depth */
  251.     {
  252.         worldColors = GetCTable( aPixelDepth);
  253.     }
  254.     
  255.     /***
  256.      *** Create the world pixel image 
  257.      ***/
  258.     
  259.     if (aPixelImage != NULL && aRowBytes != 0)        /* Use the existing pixel image */
  260.     {
  261.         HUnlock( aPixelImage);
  262.         
  263.         worldPixels = aPixelImage;
  264.         worldOwnsPixels = FALSE;    /* We don't own the pixel image */
  265.     }
  266.     else                                            /* Create a new blank pixel image */
  267.     {
  268.         long    width, height;
  269.         
  270.         width = aBoundsRect->right - aBoundsRect->left;
  271.         height = aBoundsRect->bottom - aBoundsRect->top;
  272.         
  273.         aRowBytes = ((width * aPixelDepth + 31) / 32 ) * 4;
  274.         
  275.         theSavedAlloc = SetAllocation( kAllocCanFail);
  276.         aPixelImage = NewHandleClear( height * aRowBytes);
  277.         SetAllocation( theSavedAlloc);
  278.         
  279.         FailNIL( aPixelImage);
  280.         
  281.         worldPixels = aPixelImage;
  282.         worldOwnsPixels = TRUE;        /* We own the pixel image, and must dispose of it */
  283.     }
  284.     
  285.     /***
  286.      *** Create the offscreen graphics device 
  287.      ***/
  288.     
  289.     worldDevice = NewGDevice( 0, -1L);
  290.     FailNIL( worldDevice);
  291.     
  292.     HLock(worldDevice);
  293.     {
  294.         GDPtr    gdev = *worldDevice;
  295.         
  296.         gdev->gdID = 0;
  297.         gdev->gdType = clutType;
  298.         gdev->gdResPref = 4;
  299.         gdev->gdSearchProc = NULL;
  300.         gdev->gdCompProc = NULL;
  301.         gdev->gdFlags = (1<<gdDevType) | (1<<ramInit) | (1<<noDriver) | (1<<screenActive);
  302.         gdev->gdRect = *aBoundsRect;
  303.         
  304.         HLock(gdev->gdPMap);
  305.         {
  306.             PixMapPtr    pmap = *gdev->gdPMap;
  307.             
  308.             pmap->baseAddr = NULL;
  309.             pmap->rowBytes = aRowBytes | 0x8000;
  310.             pmap->bounds = *aBoundsRect;
  311.             pmap->pixelSize = aPixelDepth;
  312.             pmap->cmpCount = 1;
  313.             pmap->cmpSize = aPixelDepth;
  314.             
  315.             DisposCTable(pmap->pmTable);
  316.             pmap->pmTable = worldColors;
  317.         }
  318.         HUnlock(gdev->gdPMap);
  319.     }
  320.     HUnlock(worldDevice);
  321.     
  322.     MakeITable( worldColors, (**worldDevice).gdITable, 4);
  323.     FailOSErr( QDError());
  324.     
  325.     /***
  326.      *** Create the offscreen graphics port 
  327.      ***/
  328.     
  329.     theSavedAlloc = SetAllocation( kAllocCanFail);
  330.     worldPort = (CGrafPtr) NewPtrClear( sizeof(CGrafPort));
  331.     SetAllocation( theSavedAlloc);
  332.     
  333.     FailNIL( worldPort);
  334.     
  335.     theSavedDevice = GetGDevice();
  336.     GetPort( &theSavedPort);
  337.     
  338.         SetGDevice( worldDevice);
  339.         OpenCPort( worldPort);
  340.         
  341.         worldPort->portRect = *aBoundsRect;
  342.         RectRgn( worldPort->visRgn, aBoundsRect);
  343.         RectRgn( worldPort->clipRgn, aBoundsRect);
  344.         
  345.     SetGDevice( theSavedDevice);
  346.     SetPort( theSavedPort);
  347.     
  348.     CView::ForceNextPrepare();
  349.     
  350.     worldIsOK = TRUE;
  351. }
  352.  
  353.  
  354. /******************************************************************************
  355.  Dispose {OVERRIDE}
  356.  
  357.         Dispose of a PixelWorld
  358.  ******************************************************************************/
  359.  
  360. void    CPixelWorld::Dispose()
  361. {
  362.     if (worldPort != NULL)
  363.     {
  364.         ClosePort( worldPort);            /* Close the color graphics port */
  365.         DisposPtr( worldPort);            /* Dispose of color graphics port */
  366.     }
  367.     
  368.     if (worldDevice != NULL)
  369.     {
  370.         DisposGDevice( worldDevice);    /* Dispose of gDevice and colorTable */
  371.     }
  372.     else
  373.     {
  374.         DisposCTable( worldColors);        /* Dispose of the colorTable */
  375.     }
  376.     
  377.     if (worldPixels != NULL && worldOwnsPixels)
  378.     {
  379.         DisposHandle( worldPixels);        /* Dispose of pixel image */
  380.     }
  381.     
  382.         /* The inherited method disposes of black & white pixel worlds */
  383.     
  384.     inherited::Dispose();
  385. }
  386.  
  387.  
  388. /******************************************************************************
  389.  WorldIsOK
  390.  
  391.         Return TRUE if world has been initialized successfully, FALSE otherwise.
  392.  ******************************************************************************/
  393.  
  394. Boolean        CPixelWorld::WorldIsOK()
  395. {
  396.     return( worldIsOK);
  397. }
  398.  
  399.  
  400. /******************************************************************************
  401.  GetPixelDepth
  402.  
  403.         Return the bounding rectangle of a PixelWorld. This rectangle defines
  404.         the size and coordinate system of the PixelWorld.
  405.  ******************************************************************************/
  406.  
  407. short    CPixelWorld::GetPixelDepth()
  408. {
  409.     return (worldDepth);
  410. }
  411.  
  412.  
  413. /******************************************************************************
  414.  GetBounds {OVERRIDE}
  415.  
  416.         Return the bounding rectangle of a PixelWorld. This rectangle defines
  417.         the size and coordinate system of the PixelWorld.
  418.  ******************************************************************************/
  419.  
  420. void    CPixelWorld::GetBounds(
  421.     LongRect        *theBounds)
  422. {
  423.     *theBounds = worldBounds;
  424. }
  425.  
  426.  
  427. /******************************************************************************
  428.  GetRowBytes
  429.  
  430.         Return row byte length for the offscreen image.
  431.  ******************************************************************************/
  432.  
  433. short    CPixelWorld::GetRowBytes()
  434. {
  435.     short    rowBytes;
  436.     
  437.     if (!worldIsOK) return (0);
  438.     
  439.     if (worldHasColor)        /* World has color */
  440.     {
  441.         rowBytes = (**worldPort->portPixMap).rowBytes;
  442.     }
  443.     else                    /* World is black and white */
  444.     {
  445.         rowBytes = macBitMap->rowBytes;
  446.     }
  447.     
  448.     rowBytes &= 0x7FFF;
  449.     return (rowBytes);
  450. }
  451.  
  452.  
  453. /******************************************************************************
  454.  PixelIsBlack {OVERRIDE}
  455.  
  456.         Determine whether the pixel at the specified coordinates is black.
  457.         Returns FALSE if the pixel is not black or it is not within the
  458.         world bounds rectangle.
  459.  ******************************************************************************/
  460.  
  461. Boolean        CPixelWorld::PixelIsBlack(
  462.     LongPt        *pixelPos)
  463. {
  464.     RGBColor    color;
  465.     
  466.     if (!worldIsOK) return (FALSE);
  467.     
  468.     if (worldHasColor)        /* World has color */
  469.     {
  470.         if (GetPixelColor( pixelPos, &color) == TRUE)    /* Inside */
  471.         {
  472.             if (color.red == 0 && color.green == 0 && color.blue == 0)
  473.                 return (TRUE);
  474.             else
  475.                 return (FALSE);
  476.         }
  477.         else
  478.         {
  479.             return (TRUE);     /* Pixel is outside and must be black */
  480.         }
  481.     }
  482.     else                    /* World is black and white */
  483.     {
  484.         return (inherited::PixelIsBlack(pixelPos));
  485.     }
  486. }
  487.  
  488.  
  489. /******************************************************************************
  490.  GetPixelColor
  491.  
  492.         Determines the color of the pixel at the specified coordinates.
  493.         Returns FALSE if the point is not within the PixelWorld.
  494.         
  495.                             *** IMPORTANT ***
  496.         
  497.         The offscreen pixel world must be active and the worldPixels
  498.         must be locked for this method to work properly.  Therefore, 
  499.         always send a BeginDrawing message before calling GetPixelColor().
  500.         When you are finished getting all the pixel colors you need,
  501.         then send the EndDrawing message to restore the previous
  502.         drawing environment.  
  503.  ******************************************************************************/
  504.  
  505. Boolean        CPixelWorld::GetPixelColor(
  506.     LongPt        *pixelPos,
  507.     RGBColor    *color)
  508. {
  509.     LongRect    bounds = worldBounds;
  510.     
  511.     if (!worldIsOK) return (FALSE);
  512.     
  513.     if (!PtInLongRect( pixelPos, &bounds))    /* Pixel is OUTSIDE bounds rectangle */
  514.         return (FALSE);
  515.     
  516.     if (worldHasColor)        /* World has color */
  517.     {
  518.         if (worldPixelsLocked)
  519.             GetCPixel((short) pixelPos->h, (short) pixelPos->v, color);    /* Get color */
  520.         else
  521.             color->red = color->green = color->blue = 0;        /* Black */
  522.     }
  523.     else                    /* World is black and white */
  524.     {
  525.         if (inherited::PixelIsBlack(pixelPos))
  526.             color->red = color->green = color->blue = 0;        /* Black */
  527.         else
  528.             color->red = color->green = color->blue = 65535;    /* White */
  529.     }
  530.     
  531.     return(TRUE);                            /* Pixel is INSIDE bounds rectangle */
  532. }
  533.  
  534.  
  535. /******************************************************************************
  536.  GetHandleToPixels
  537.  
  538.         Return a handle to the pixel image.  The handle is only valid 
  539.         when the offscreen world is in color.  If the offscreen world 
  540.         is in black and white, a NULL handle is returned.  
  541.  ******************************************************************************/
  542.  
  543. Handle    CPixelWorld::GetHandleToPixels()
  544. {
  545.     return( worldPixels);
  546. }
  547.  
  548.  
  549. /******************************************************************************
  550.  GetPointerToPixels
  551.  
  552.         Return a pointer to the pixel image.  Works for color and black/white 
  553.         images as well.  
  554.  ******************************************************************************/
  555.  
  556. Ptr        CPixelWorld::GetPointerToPixels()
  557. {
  558.     if (!worldIsOK) return (NULL);
  559.     
  560.     if (worldHasColor)        /* World has color */
  561.     {
  562.         return( (Ptr) *worldPixels);
  563.     }
  564.     else                    /* World is black and white */
  565.     {
  566.         return( (Ptr) macBitMap->baseAddr);
  567.     }
  568. }
  569.  
  570.  
  571. /******************************************************************************
  572.  SetBoundsOrigin {OVERRIDE}
  573.  
  574.         Set the coordinates of the top left corner of the bounds of a
  575.         PixelWorld. This changes the coordinate system of the PixelWorld.
  576.         Note that the visRgn and clipRgn of the PixelWorld are reset.
  577.  ******************************************************************************/
  578.  
  579. void    CPixelWorld::SetBoundsOrigin(
  580.     short        hOrigin,
  581.     short        vOrigin)
  582. {
  583.     Rect        bounds;
  584.     
  585.     if (!worldIsOK) return;
  586.     
  587.     bounds.left = hOrigin;
  588.     bounds.top = vOrigin;
  589.     bounds.right = hOrigin + (worldBounds.right - worldBounds.left);
  590.     bounds.bottom = vOrigin + (worldBounds.bottom - worldBounds.top);
  591.     
  592.     worldBounds.left = bounds.left;
  593.     worldBounds.top = bounds.top;
  594.     worldBounds.right = bounds.right;
  595.     worldBounds.bottom = bounds.bottom;
  596.     
  597.     if (worldHasColor)            /* World has color */
  598.     {
  599.         HLock(worldDevice);
  600.         {
  601.             GDPtr    gdev = *worldDevice;
  602.             
  603.             (**gdev->gdPMap).bounds = bounds;
  604.             gdev->gdRect = bounds;
  605.         }
  606.         HUnlock(worldDevice);
  607.         
  608.         (**worldPort->portPixMap).bounds = bounds;
  609.         worldPort->portRect = bounds;
  610.         RectRgn( worldPort->visRgn, &bounds);
  611.         RectRgn( worldPort->clipRgn, &bounds);
  612.     }
  613.     else                        /* World is black and white */
  614.     {
  615.         macBitMap->bounds = bounds;
  616.         macPort->portBits.bounds = bounds;
  617.         macPort->portRect = bounds;
  618.         
  619.         RectRgn( macPort->visRgn, &bounds);
  620.         RectRgn( macPort->clipRgn, &bounds);
  621.     }
  622. }
  623.  
  624.  
  625. /******************************************************************************
  626.  BeginDrawing {OVERRIDE}
  627.  
  628.                             *** IMPORTANT ***
  629.         
  630.         Always send this message before performing any drawing to the 
  631.         offscreen pixel world. This function saves the current GDevice 
  632.         and GrafPort, activates the worldDevice and worldPort, and sends
  633.         the message LockWorld( TRUE) to lock down the pixel image.  
  634.         
  635.         If you do not call BeginDrawing() before drawing to the offscreen 
  636.         world, the PixMaps of the worldDevice and worldPort will have NULL 
  637.         baseAddr pointers and any drawing calls will probably cause a 
  638.         CRASH since low memory addresses will be overwritten !!!!!!  
  639.  ******************************************************************************/
  640.  
  641. void    CPixelWorld::BeginDrawing()
  642. {
  643.     ActivateWorld();
  644. }
  645.  
  646.  
  647. /******************************************************************************
  648.  EndDrawing {OVERRIDE}
  649.  
  650.                             *** IMPORTANT ***
  651.         
  652.         Always send this message after performing any drawing to the
  653.         offscreen pixel world.  This function resets the port to the 
  654.         way it was before the BeginDrawing message.  It restores the 
  655.         saved GDevice and GrafPort, and unlocks the pixel image.  
  656.  ******************************************************************************/
  657.  
  658. void    CPixelWorld::EndDrawing()
  659. {
  660.     DeactivateWorld();
  661. }
  662.  
  663.  
  664. /******************************************************************************
  665.  ActivateWorld
  666.  
  667.         Activates the offscreen pixel world so that all drawing will take
  668.         place in the offscreen graphics port.  The currently active graphics 
  669.         device and port are saved so they can be restored later.  
  670.  ******************************************************************************/
  671.  
  672. void    CPixelWorld::ActivateWorld()
  673. {
  674.     if (!worldIsOK) return;
  675.     
  676.     if (worldHasColor)            /* World has color */
  677.     {
  678.         saveDevice = GetGDevice();
  679.         GetPort( &savePort);
  680.         
  681.         LockWorld( TRUE);
  682.         
  683.         SetGDevice( worldDevice);
  684.         SetPort( worldPort);
  685.     }
  686.     else                        /* World is black and white */
  687.     {
  688.         GetPort( &savePort);
  689.         SetPort( macPort);
  690.     }
  691. }
  692.  
  693.  
  694. /******************************************************************************
  695.  DeactivateWorld
  696.  
  697.         Restores the previously active graphics device and port.
  698.  ******************************************************************************/
  699.  
  700. void    CPixelWorld::DeactivateWorld()
  701. {
  702.     if (!worldIsOK) return;
  703.     
  704.     if (worldHasColor)            /* World has color */
  705.     {
  706.         LockWorld( FALSE);
  707.         
  708.         if (saveDevice != NULL) SetGDevice( saveDevice);
  709.         if (savePort != NULL) SetPort( savePort);
  710.         
  711.         saveDevice = NULL;
  712.         savePort = NULL;
  713.     }
  714.     else
  715.     {
  716.         if (savePort != NULL) SetPort( savePort);
  717.         savePort = NULL;
  718.     }
  719. }
  720.  
  721.  
  722. /******************************************************************************
  723.  LockWorld
  724.  
  725.         Lock or unlock the worldPixels handle according to the flag setLock.
  726.         If setLock is true, then the worldPixels handle is locked and the 
  727.         de-referenced handle is put into the baseAddr field of worldDevice 
  728.         and worldPort PixMap structures.  
  729.  ******************************************************************************/
  730.  
  731. Boolean        CPixelWorld::LockWorld(
  732.     Boolean        setLock)
  733. {
  734.     if (!worldIsOK) return (FALSE);
  735.  
  736.     if (worldHasColor)
  737.     {
  738.         if (worldPixelsLocked)
  739.         {
  740.             if (!setLock)
  741.             {
  742.                 PixMapHandle    hMap;
  743.                 
  744.                 HUnlock(worldPixels);
  745.                 
  746.                 hMap = (**worldDevice).gdPMap;
  747.                 (**hMap).baseAddr = NULL;
  748.                 
  749.                 hMap = worldPort->portPixMap;
  750.                 (**hMap).baseAddr = NULL;
  751.                 
  752.                 worldPixelsLocked = FALSE;
  753.             }
  754.             
  755.             return (TRUE);
  756.         }
  757.         else
  758.         {
  759.             if (setLock)
  760.             {
  761.                 PixMapHandle    hMap;
  762.                 
  763.                 MoveHHi(worldPixels);
  764.                 HLock(worldPixels);
  765.                 
  766.                 hMap = (**worldDevice).gdPMap;
  767.                 (**hMap).baseAddr = (Ptr) *worldPixels;
  768.                 
  769.                 hMap = worldPort->portPixMap;
  770.                 (**hMap).baseAddr = (Ptr) *worldPixels;
  771.                 
  772.                 worldPixelsLocked = TRUE;
  773.             }
  774.             
  775.             return (FALSE);
  776.         }
  777.     }
  778.     
  779.     return (FALSE);
  780. }
  781.  
  782.  
  783. /******************************************************************************
  784.  SaveColors
  785.  
  786.         Save the current foreground and background colors.  
  787.  ******************************************************************************/
  788.  
  789. void    CPixelWorld::SaveColors()
  790. {
  791.     RGBColor    color;
  792.     
  793.     GetForeColor( &color);
  794.     saveFgColor = color;
  795.     
  796.     GetBackColor( &color);
  797.     saveBgColor = color;
  798. }
  799.  
  800.  
  801. /******************************************************************************
  802.  RestoreColors
  803.  
  804.         Restore the original foreground and background colors.  
  805.  ******************************************************************************/
  806.  
  807. void    CPixelWorld::RestoreColors()
  808. {
  809.     RGBColor    color;
  810.     
  811.     color = saveFgColor;
  812.     RGBForeColor( &color);
  813.     
  814.     color = saveBgColor;
  815.     RGBBackColor( &color);
  816. }
  817.  
  818.  
  819. /******************************************************************************
  820.  CopyFromColors
  821.  
  822.         The CopyFrom() method calls this routine to set the foreground 
  823.         and background colors just before calling CopyBits.  By setting 
  824.         the foreground to BLACK and the background to WHITE, this method 
  825.         ensures that the image is copied without colorization.  This means 
  826.         that the colors of the original image and the copy will match.  
  827.         
  828.         If you want to colorize the copy of the image so its colors are 
  829.         different from the original, create a subclass in which you override 
  830.         this method and set the foregound and background colors appropriately.  
  831.  ******************************************************************************/
  832.  
  833. void    CPixelWorld::CopyFromColors()
  834. {
  835.     RGBColor    color;
  836.     
  837.         /* Black foreground */
  838.     color.red = color.green = color.blue = 0x0000;
  839.     RGBForeColor( &color);
  840.     
  841.         /* White background */    
  842.     color.red = color.green = color.blue = 0xFFFF;
  843.     RGBBackColor( &color);
  844. }
  845.  
  846.  
  847. /******************************************************************************
  848.  CopyToColors
  849.  
  850.         The CopyTo() method calls this routine to set the foreground 
  851.         and background colors just before calling CopyBits.  By setting 
  852.         the foreground to BLACK and the background to WHITE, this method 
  853.         ensures that the image is copied without colorization.  This means 
  854.         that the colors of the original image and the copy will match.  
  855.         
  856.         If you want to colorize the copy of the image so its colors are 
  857.         different from the original, create a subclass in which you override 
  858.         this method and set the foregound and background colors appropriately.  
  859.  ******************************************************************************/
  860.  
  861. void    CPixelWorld::CopyToColors()
  862. {
  863.     RGBColor    color;
  864.     
  865.         /* Black foreground */
  866.     color.red = color.green = color.blue = 0x0000;
  867.     RGBForeColor( &color);
  868.     
  869.         /* White background */    
  870.     color.red = color.green = color.blue = 0xFFFF;
  871.     RGBBackColor( &color);
  872. }
  873.  
  874.  
  875. /******************************************************************************
  876.  CopyFrom {OVERRIDE}
  877.  
  878.         Copy bits from a PixelWorld to the bit map of the current port. The
  879.         fromRect is a rectangle in this PixelWorld (source rect), and the
  880.         toRect is a rectangle in the current port's bit map (dest rect).
  881.         maskRgn is a clipping region specified in the same coords as the
  882.         dest rect, i.e., the coords of the current port. A NULL maskRgn means
  883.         that no extra clipping is performed. Copying takes place using the
  884.         transfer mode stored in the xferMode instance variable.
  885.  ******************************************************************************/
  886.  
  887. void    CPixelWorld::CopyFrom(
  888.     LongRect    *fromRect,
  889.     LongRect    *toRect,
  890.     RgnHandle    maskRgn)
  891. {
  892.     if (!worldIsOK) return;
  893.     
  894.     if (worldHasColor)            /* World has color */
  895.     {
  896.         Boolean        savedLock;
  897.         
  898.         SaveColors();
  899.         CopyFromColors();
  900.         savedLock = LockWorld( TRUE);
  901.         
  902.         LCopyBits( &((GrafPtr)worldPort)->portBits, &thePort->portBits, 
  903.                     fromRect, toRect, xferMode, maskRgn);
  904.         
  905.         LockWorld( savedLock);
  906.         RestoreColors();
  907.     }
  908.     else                        /* World is black and white */
  909.     {                                    /* Call the inherited method */
  910.         inherited::CopyFrom( fromRect, toRect, maskRgn);
  911.     }
  912. }
  913.  
  914.  
  915. /******************************************************************************
  916.  CopyTo {OVERRIDE}
  917.  
  918.         Copy bits to a PixelWorld from the bit map of the current port. The
  919.         fromRect is a rectangle in the current port's bit map (source rect),
  920.         and the toRect is a rectangle in this PixelWorld (dest rect). maskRgn is
  921.         a clipping region specified in the same coords as the dest rect,
  922.         i.e., the coords of this PixelWorld. A NULL maskRgn means that no extra
  923.         clipping is performed. Copying takes place using the transfer mode
  924.         stored in the xferMode instance variable.
  925.  ******************************************************************************/
  926.  
  927. void    CPixelWorld::CopyTo(
  928.     LongRect    *fromRect,
  929.     LongRect    *toRect,
  930.     RgnHandle    maskRgn)
  931. {
  932.     if (!worldIsOK) return;
  933.     
  934.     if (worldHasColor)            /* World has color */
  935.     {
  936.         Boolean        savedLock;
  937.         
  938.         SaveColors();
  939.         CopyToColors();
  940.         savedLock = LockWorld( TRUE);
  941.         
  942.         LCopyBits( &thePort->portBits, &((GrafPtr)worldPort)->portBits, 
  943.                     fromRect, toRect, xferMode, maskRgn);
  944.         
  945.         LockWorld( savedLock);
  946.         RestoreColors();
  947.     }
  948.     else                        /* World is black and white */
  949.     {                                    /* Call the inherited method */
  950.         inherited::CopyTo( fromRect, toRect, maskRgn);
  951.     }
  952. }
  953.  
  954.  
  955.